home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '87 / Source ƒ.sea / Source ƒ / emacs source ƒ / SPAWN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-28  |  13.8 KB  |  511 lines  |  [TEXT/MARC]

  1. /*    Spawn:    various DOS access commands
  2.         for MicroEMACS
  3. */
  4.  
  5. #include        <stdio.h>
  6. #include    "estruct.h"
  7. #include        "edef.h"
  8.  
  9. #if     AMIGA
  10. #define  NEW   1006
  11. #endif
  12.  
  13. #if     VMS
  14. #define EFN     0                               /* Event flag.          */
  15.  
  16. #include        <ssdef.h>                       /* Random headers.      */
  17. #include        <stsdef.h>
  18. #include        <descrip.h>
  19. #include        <iodef.h>
  20.  
  21. extern  int     oldmode[3];                     /* In "termio.c"        */
  22. extern  int     newmode[3];                     /* In "termio.c"        */
  23. extern  short   iochan;                         /* In "termio.c"        */
  24. #endif
  25.  
  26. #if     V7 | USG | BSD
  27. #include        <signal.h>
  28. extern int vttidy();
  29. #endif
  30.  
  31. #if    MSDOS & MSC
  32. #include    <process.h>
  33. #define    system(a)    spawnlp(P_WAIT, a, NULL)
  34. #endif
  35.  
  36. /*
  37.  * Create a subjob with a copy of the command intrepreter in it. When the
  38.  * command interpreter exits, mark the screen as garbage so that you do a full
  39.  * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  40.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  41.  */
  42. spawncli(f, n)
  43. {
  44. #if     AMIGA
  45.         long newcli;
  46.  
  47.         newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  48.         mlwrite("[Starting new CLI]");
  49.         sgarbf = TRUE;
  50.         Execute("", newcli, 0);
  51.         Close(newcli);
  52.         return(TRUE);
  53. #endif
  54.  
  55. #if     V7 | USG | BSD
  56.         register char *cp;
  57.         char    *getenv();
  58. #endif
  59. #if     VMS
  60.         movecursor(term.t_nrow, 0);             /* In last line.        */
  61.         mlputs("[Starting DCL]\r\n");
  62.         (*term.t_flush)();                      /* Ignore "ttcol".      */
  63.         sgarbf = TRUE;
  64.         return (sys(NULL));                     /* NULL => DCL.         */
  65. #endif
  66. #if     CPM
  67.         mlwrite("Not in CP/M-86");
  68. #endif
  69. #if     MSDOS & AZTEC
  70.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  71.         (*term.t_flush)();
  72.     (*term.t_kclose)();
  73.     system("command.com");
  74.     (*term.t_kopen)();
  75.         sgarbf = TRUE;
  76.         return(TRUE);
  77. #endif
  78. #if     MSDOS & LATTICE
  79.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  80.         (*term.t_flush)();
  81.     (*term.t_kclose)();
  82.         sys("\\command.com", "");               /* Run CLI.             */
  83.     (*term.t_kopen)();
  84.         sgarbf = TRUE;
  85.         return(TRUE);
  86. #endif
  87. #if     V7 | USG | BSD
  88.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  89.         (*term.t_flush)();
  90.         ttclose();                              /* stty to old settings */
  91.         if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  92.                 system(cp);
  93.         else
  94. #if    BSD
  95.                 system("exec /bin/csh");
  96. #else
  97.                 system("exec /bin/sh");
  98. #endif
  99.         sgarbf = TRUE;
  100.         sleep(2);
  101.         ttopen();
  102.         return(TRUE);
  103. #endif
  104. }
  105.  
  106. #if    BSD
  107.  
  108. bktoshell()        /* suspend MicroEMACS and wait to wake up */
  109. {
  110.     int pid;
  111.  
  112.     vttidy();
  113.     pid = getpid();
  114.     kill(pid,SIGTSTP);
  115. }
  116.  
  117. rtfrmshell()
  118. {
  119.     ttopen();
  120.     curwp->w_flag = WFHARD;
  121.     sgarbf = TRUE;
  122. }
  123. #endif
  124.  
  125. /*
  126.  * Run a one-liner in a subjob. When the command returns, wait for a single
  127.  * character to be typed, then mark the screen as garbage so a full repaint is
  128.  * done. Bound to "C-X !".
  129.  */
  130. spawn(f, n)
  131. {
  132.         register int    s;
  133.         char            line[NLINE];
  134. #if     AMIGA
  135.         long newcli;
  136.  
  137.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  138.                 return (s);
  139.         newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  140.         Execute(line,0,newcli);
  141.         Close(newcli);
  142.         (*term.t_getchar)();     /* Pause.               */
  143.         sgarbf = TRUE;
  144.         return(TRUE);
  145. #endif
  146. #if     VMS
  147.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  148.                 return (s);
  149.         (*term.t_putchar)('\n');                /* Already have '\r'    */
  150.         (*term.t_flush)();
  151.         s = sys(line);                          /* Run the command.     */
  152.         mlputs("\r\n\n[End]");                  /* Pause.               */
  153.         (*term.t_flush)();
  154.         (*term.t_getchar)();
  155.         sgarbf = TRUE;
  156.         return (s);
  157. #endif
  158. #if     CPM
  159.         mlwrite("Not in CP/M-86");
  160.         return (FALSE);
  161. #endif
  162. #if     MSDOS
  163.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  164.                 return(s);
  165.     movecursor(term.t_nrow - 1, 0);
  166.     (*term.t_kclose)();
  167.         system(line);
  168.     (*term.t_kopen)();
  169.         mlputs("\r\n\n[End]");                  /* Pause.               */
  170.         (*term.t_getchar)();     /* Pause.               */
  171.         sgarbf = TRUE;
  172.         return (TRUE);
  173. #endif
  174. #if     V7 | USG | BSD
  175.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  176.                 return (s);
  177.         (*term.t_putchar)('\n');                /* Already have '\r'    */
  178.         (*term.t_flush)();
  179.         ttclose();                              /* stty to old modes    */
  180.         system(line);
  181.         ttopen();
  182.         mlputs("[End]");                        /* Pause.               */
  183.         (*term.t_flush)();
  184.         while ((s = (*term.t_getchar)()) != '\r' && s != ' ')
  185.                 ;
  186.         sgarbf = TRUE;
  187.         return (TRUE);
  188. #endif
  189. }
  190.  
  191. /*
  192.  * Pipe a one line command into a window
  193.  * Bound to ^X @
  194.  */
  195. pipe(f, n)
  196. {
  197.         register int    s;    /* return status from CLI */
  198.     register WINDOW *wp;    /* pointer to new window */
  199.     register BUFFER *bp;    /* pointer to buffer to zot */
  200.         char    line[NLINE];    /* command line send to shell */
  201.     static char bname[] = "command";
  202.  
  203. #if    AMIGA
  204.     static char filnam[] = "ram:command";
  205.         long newcli;
  206. #else
  207.     static char filnam[] = "command";
  208. #endif
  209.  
  210. #if     VMS
  211.     mlwrite("Not availible under VMS");
  212.     return(FALSE);
  213. #endif
  214. #if     CPM
  215.         mlwrite("Not availible under CP/M-86");
  216.         return(FALSE);
  217. #endif
  218.  
  219.     /* get the command to pipe in */
  220.         if ((s=mlreply("@", line, NLINE)) != TRUE)
  221.                 return(s);
  222.  
  223.     /* get rid of the command output buffer if it exists */
  224.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  225.         /* try to make sure we are off screen */
  226.         wp = wheadp;
  227.         while (wp != NULL) {
  228.             if (wp->w_bufp == bp) {
  229.                 onlywind(FALSE, 1);
  230.                 break;
  231.             }
  232.             wp = wp->w_wndp;
  233.         }
  234.         if (zotbuf(bp) != TRUE)
  235.             return(FALSE);
  236.     }
  237.  
  238. #if     AMIGA
  239.         newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  240.     strcat(line, " >");
  241.     strcat(line, filnam);
  242.         Execute(line,0,newcli);
  243.     s = TRUE;
  244.         Close(newcli);
  245.         sgarbf = TRUE;
  246. #endif
  247. #if     MSDOS
  248.     strcat(line," >");
  249.     strcat(line,filnam);
  250.     movecursor(term.t_nrow - 1, 0);
  251.     (*term.t_kclose)();
  252.         system(line);
  253.     (*term.t_kopen)();
  254.         sgarbf = TRUE;
  255.     s = TRUE;
  256. #endif
  257. #if     V7 | USG | BSD
  258.         (*term.t_putchar)('\n');                /* Already have '\r'    */
  259.         (*term.t_flush)();
  260.         ttclose();                              /* stty to old modes    */
  261.     strcat(line,">");
  262.     strcat(line,filnam);
  263.         system(line);
  264.         ttopen();
  265.         (*term.t_flush)();
  266.         sgarbf = TRUE;
  267.         s = TRUE;
  268. #endif
  269.  
  270.     if (s != TRUE)
  271.         return(s);
  272.  
  273.     /* split the current window to make room for the command output */
  274.     if (splitwind(FALSE, 1) == FALSE)
  275.             return(FALSE);
  276.  
  277.     /* and read the stuff in */
  278.     if (getfile(filnam, FALSE) == FALSE)
  279.         return(FALSE);
  280.  
  281.     /* make this window in VIEW mode, update all mode lines */
  282.     curwp->w_bufp->b_mode |= MDVIEW;
  283.     wp = wheadp;
  284.     while (wp != NULL) {
  285.         wp->w_flag |= WFMODE;
  286.         wp = wp->w_wndp;
  287.     }
  288.  
  289.     /* and get rid of the temporary file */
  290.     unlink(filnam);
  291.     return(TRUE);
  292. }
  293.  
  294. /*
  295.  * filter a buffer through an external DOS program
  296.  * Bound to ^X #
  297.  */
  298. filter(f, n)
  299.  
  300. {
  301.         register int    s;    /* return status from CLI */
  302.     register BUFFER *bp;    /* pointer to buffer to zot */
  303.         char line[NLINE];    /* command line send to shell */
  304.     char tmpnam[NFILEN];    /* place to store real file name */
  305.     static char bname1[] = "fltinp";
  306.  
  307. #if    AMIGA
  308.     static char filnam1[] = "ram:fltinp";
  309.     static char filnam2[] = "ram:fltout";
  310.         long newcli;
  311. #else
  312.     static char filnam1[] = "fltinp";
  313.     static char filnam2[] = "fltout";
  314. #endif
  315.  
  316. #if     VMS
  317.     mlwrite("Not availible under VMS");
  318.     return(FALSE);
  319. #endif
  320. #if     CPM
  321.         mlwrite("Not availible under CP/M-86");
  322.         return(FALSE);
  323. #endif
  324.  
  325.     /* get the filter name and its args */
  326.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  327.                 return(s);
  328.  
  329.     /* setup the proper file names */
  330.     bp = curbp;
  331.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  332.     strcpy(bp->b_fname, bname1);    /* set it to our new one */
  333.  
  334.     /* write it out, checking for errors */
  335.     if (writeout(filnam1) != TRUE) {
  336.         mlwrite("[Cannot write filter file]");
  337.         strcpy(bp->b_fname, tmpnam);
  338.         return(FALSE);
  339.     }
  340.  
  341. #if     AMIGA
  342.         newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  343.     strcat(line, " <ram:fltinp >ram:fltout");
  344.         Execute(line,0,newcli);
  345.     s = TRUE;
  346.         Close(newcli);
  347.         sgarbf = TRUE;
  348. #endif
  349. #if     MSDOS
  350.     strcat(line," <fltinp >fltout");
  351.     movecursor(term.t_nrow - 1, 0);
  352.     (*term.t_kclose)();
  353.         system(line);
  354.     (*term.t_kopen)();
  355.         sgarbf = TRUE;
  356.     s = TRUE;
  357. #endif
  358. #if     V7 | USG | BSD
  359.         (*term.t_putchar)('\n');                /* Already have '\r'    */
  360.         (*term.t_flush)();
  361.         ttclose();                              /* stty to old modes    */
  362.     strcat(line," <fltinp >fltout");
  363.         system(line);
  364.         ttopen();
  365.         (*term.t_flush)();
  366.         sgarbf = TRUE;
  367.         s = TRUE;
  368. #endif
  369.  
  370.     /* on failure, escape gracefully */
  371.     if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  372.         mlwrite("[Execution failed]");
  373.         strcpy(bp->b_fname, tmpnam);
  374.         unlink(filnam1);
  375.         unlink(filnam2);
  376.         return(s);
  377.     }
  378.  
  379.     /* reset file name */
  380.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  381.     bp->b_flag |= BFCHG;        /* flag it as changed */
  382.  
  383.     /* and get rid of the temporary file */
  384.     unlink(filnam1);
  385.     unlink(filnam2);
  386.     return(TRUE);
  387. }
  388.  
  389. #if     VMS
  390. /*
  391.  * Run a command. The "cmd" is a pointer to a command string, or NULL if you
  392.  * want to run a copy of DCL in the subjob (this is how the standard routine
  393.  * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
  394.  * and the way out, because DCL does not want the channel to be in raw mode.
  395.  */
  396. sys(cmd)
  397. register char   *cmd;
  398. {
  399.         struct  dsc$descriptor  cdsc;
  400.         struct  dsc$descriptor  *cdscp;
  401.         long    status;
  402.         long    substatus;
  403.         long    iosb[2];
  404.  
  405.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  406.                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
  407.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  408.                 return (FALSE);
  409.         cdscp = NULL;                           /* Assume DCL.          */
  410.         if (cmd != NULL) {                      /* Build descriptor.    */
  411.                 cdsc.dsc$a_pointer = cmd;
  412.                 cdsc.dsc$w_length  = strlen(cmd);
  413.                 cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  414.                 cdsc.dsc$b_class   = DSC$K_CLASS_S;
  415.                 cdscp = &cdsc;
  416.         }
  417.         status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
  418.         if (status != SS$_NORMAL)
  419.                 substatus = status;
  420.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  421.                           newmode, sizeof(newmode), 0, 0, 0, 0);
  422.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  423.                 return (FALSE);
  424.         if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
  425.                 return (FALSE);
  426.         return (TRUE);
  427. }
  428. #endif
  429.  
  430. #if    ~AZTEC & MSDOS
  431.  
  432. /*
  433.  * This routine, once again by Bob McNamara, is a C translation of the "system"
  434.  * routine in the MWC-86 run time library. It differs from the "system" routine
  435.  * in that it does not unconditionally append the string ".exe" to the end of
  436.  * the command name. We needed to do this because we want to be able to spawn
  437.  * off "command.com". We really do not understand what it does, but if you don't
  438.  * do it exactly "malloc" starts doing very very strange things.
  439.  */
  440. sys(cmd, tail)
  441. char    *cmd;
  442. char    *tail;
  443. {
  444. #if MWC_86
  445.         register unsigned n;
  446.         extern   char     *__end;
  447.  
  448.         n = __end + 15;
  449.         n >>= 4;
  450.         n = ((n + dsreg() + 16) & 0xFFF0) + 16;
  451.         return(execall(cmd, tail, n));
  452. #endif
  453.  
  454. #if LATTICE
  455.         return(forklp(cmd, tail, (char *)NULL));
  456. #endif
  457.  
  458. #if    MSC
  459.     return(spawnlp(P_WAIT, cmd, tail, NULL));
  460. #endif
  461. }
  462. #endif
  463.  
  464. #if    MSDOS & LATTICE
  465. /*    System: a modified version of lattice's system() function
  466.         that detects the proper switchar and uses it
  467.         written by Dana Hogget                */
  468.  
  469. system(cmd)
  470.  
  471. char *cmd;    /*  Incoming command line to execute  */
  472.  
  473. {
  474.     char *getenv();
  475.     static char *swchar = "/C";    /*  Execution switch  */
  476.     union REGS inregs;    /*  parameters for dos call  */
  477.     union REGS outregs;    /*  Return results from dos call  */
  478.     char *shell;        /*  Name of system command processor  */
  479.     char *p;        /*  Temporary pointer  */
  480.     int ferr;        /*  Error condition if any  */
  481.  
  482.     /*  get name of system shell  */
  483.     if ((shell = getenv("COMSPEC")) == NULL) {
  484.         return (-1);        /*  No shell located  */
  485.     }
  486.  
  487.     p = cmd;
  488.     while (isspace(*p)) {        /*  find out if null command */
  489.         p++;
  490.     }
  491.  
  492.     /**  If the command line is not empty, bring up the shell  **/
  493.     /**  and execute the command.  Otherwise, bring up the     **/
  494.     /**  shell in interactive mode.   **/
  495.  
  496.     if (p && *p) {
  497.         /**  detect current switch character and us it  **/
  498.         inregs.h.ah = 0x37;    /*  get setting data  */
  499.         inregs.h.al = 0x00;    /*  get switch character  */
  500.         intdos(&inregs, &outregs);
  501.         *swchar = outregs.h.dl;
  502.         ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
  503.     } else {
  504.         ferr = forkl(shell, "command", (char *)NULL);
  505.     }
  506.  
  507.     return (ferr ? ferr : wait());
  508. }
  509. #endif
  510.  
  511.